// 全局变量
var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
var base64DecodeChars = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
];

String.prototype.trim = function() { 
	return this.replace(/(^\s*)|(\s*$)/g, "");
};

String.prototype.getMain = function() {
	var index = this.indexOf("?");
	if (index >= 0) {
		return this.substring(0, index);
	}
	return this;
};

String.prototype.getDomain = function() {
	var index = this.indexOf("/", 8);
	if (index >= 0) {
		return this.substring(0, index);
	}
	return this;
};

String.prototype.getPath = function() {
	var index = this.indexOf("/", 8);
	if (index >= 0) {
		return this.substring(index);
	}
	return this;
};

String.prototype.endsWith = function(str){  
	if(str == null || str=="" || this.length == 0 || str.length > this.length) { 
	  	return false;  
	}
	
	if(this.substring(this.length-str.length) == str) {
	  	return true;  
	}

	return false;   
};

String.prototype.startWith = function(str){  
	if(str == null || str=="" || this.length == 0 || str.length > this.length) { 
	  	return false;  
	}
	if(this.substring(0, str.length) == str){
		return true;
	}
	return false;
};

String.prototype.getArgs = function() {
	var result = {};
	var index = this.indexOf("?");
	if (index >= 0) {
		var queryList = this.substring(index + 1);
		var args = queryList.split('&');
		for (var i = 0; i < args.length; i++) {
			var str = args[i];
			var arg = str.split("="); 
			if(arg.length <= 1) {
				continue;
			}
			
			result[arg[0].trim()] = arg[1].trim();
		}
	}
	return result;
};

/*
Dictionary类：本类实现了字典功能，所有方法、属性都模仿System..Collection.Generic.Dictionary类
构造函数：
	Dictionary()
属性：
	compareMode：比较模式，0——二进制   1——文本
	count：字典中的项目数
	throwException：遇到错误时，是否抛出异常
方法：
	item(key)：获取指定键对应的值
	keys()：获取键数组
	values()：获取值数组
	add(key,value)：将指定的键和值添加到字典中
	batchAdd(keys,values)：尝试将指定的键和值数组添加到字典中，如果全部添加成功，返回true；否则返回false。
	clear()：清除字典中的所有项
	containsKey(key)：字典中是否包含指定的键
	containsValue(value)：字典中是否包含指定的值
	remove(key)：删除字典中指定的键
	tryGetValue(key,defaultValue)：尝试获取字典中指定键对应的值，如果键不存在，返回默认值
	toString()：返回字典中所有键和值组成的字符串，格式为“逗号分隔的键列表  分号  逗号分隔的值列表”
*/
utils = new Object();
utils.Dictionary = function() {
	var me = this;			//将this指针保存到变量me中
	this.compareMode = 1;		//比较关键字是否相等的模式，0——二进制；1——文本
	this.count = 0;			//字典中的项目数
	this.arrKeys = new Array();	//关键字数组
	this.arrValues = new Array();	//值数组
	this.throwException = true;	//遇到错误时，是否用throw语句抛出异常

	this.item = function(key) { //Item方法，获取指定键对应的值。如果键不存在，引发异常
		var idx = getElementIndexInArray(me.arrKeys,key);
		if(idx != -1) {
			return me.arrValues[idx];
		} else {
			if(me.throwException) {
			    throw "Exception when get the value, the key is not exist。";
            }
		}
	};
	
	this.keys = function() { //获取包含所有键的数组
		return me.arrKeys;
	};
	
	this.values = function() { //获取包含所有值的数组
		return me.arrValues;
	};
	
	this.add = function(key,value) { //将指定的键和值添加到字典中
		if(checkKey(key)) {
			me.arrKeys[me.count] = key;
			me.arrValues[me.count] = value;
			me.count++;
		} else {
			if(me.throwException) {
				throw "Exception when add to the dictionary，maybe the key allready exists.";
            }
		}
	};
	
	this.batchAdd = function(keys,values)	{ //批量增加键和值数组项，如果成功，增加所有的项，返回true；否则，不增加任何项，返回false。
		var bSuccessed = false;
		if (keys != null && keys != undefined && values != null && values != undefined) {
			if(keys.length == values.length && keys.length > 0)	 {//键和值数组的元素数目必须相同
				var allKeys = me.arrKeys.concat(keys);	//组合字典中原有的键和新键到一个新数组
				if(!isArrayElementRepeat(allKeys)) { //检验新数组是否存在重复的键
					me.arrKeys = allKeys;
					me.arrValues = me.arrValues.concat(values);
					me.count = me.arrKeys.length;
					bSuccessed=true;
				}
			}
		}
		return bSuccessed;
	};
	
	this.clear = function() { //清除字典中的所有键和值
		if(me.count != 0) {
			me.arrKeys.splice(0, me.count);
			me.arrValues.splice(0, me.count);
			me.count = 0;
		}
	};
	
	this.containsKey = function(key) { //确定字典中是否包含指定的键
		return getElementIndexInArray(me.arrKeys,key) != -1;
	};
	
	this.containsValue = function(value) { //确定字典中是否包含指定的值
		return getElementIndexInArray(me.arrValues,value) != -1;
	};
	
	this.remove = function(key) { //从字典中移除指定键的值
		var idx = getElementIndexInArray(me.arrKeys,key);
		if(idx != -1) {
			me.arrKeys.splice(idx,1);
			me.arrValues.splice(idx,1);
			me.count--;
			return true;
		}

		return false;
	};
	
	this.tryGetValue = function(key, defaultValue)	{ //尝试从字典中获取指定键对应的值，如果指定键不存在，返回默认值defaultValue
		var idx = getElementIndexInArray(me.arrKeys,key);
		if(idx != -1) {
			return me.arrValues[idx];
		}

		return defaultValue;
	};
	
	this.toString = function()  { //返回字典的字符串值，排列为： 逗号分隔的键列表  分号  逗号分隔的值列表
		if(me.Count == 0) {
			return "";
        }

		return me.arrKeys.toString() + ";" + me.arrValues.toString();
	};
	
	function checkKey(key) { //检查key是否合格，是否与已有的键重复
		if(key == null || key == undefined || key == "" || key == NaN) {
			return false;
        }

		return !me.containsKey(key);
	};
	
	function getElementIndexInArray(arr,e) { //得到指定元素在数组中的索引，如果元素存在于数组中，返回所处的索引；否则返回-1。
		var idx = -1;	//得到的索引
		var i;		//用于循环的变量
		if(!(arr == null || arr == undefined || typeof(arr) != "object")) {
			try {
				for(i = 0; i< arr.length; i++) {
					var bEqual;
					if(me.compareMode == 0) {
						bEqual = (arr[i] === e);	//二进制比较
                    } else {
						bEqual = (arr[i] == e);		//文本比较
                    }
					if(bEqual) {
						idx = i;
						break;
					}
				}
			} catch(error) {
			}
		}
		return idx;
	}
	
	function isArrayElementRepeat(arr){
		var bRepeat = false;
		if(arr != null && arr != undefined && typeof(arr) == "object") { //判断一个数组中的元素是否存在重复的情况，如果存在重复的元素，返回true，否则返回false。
			var i;
			for(i=0;i<arr.length-1;i++) {
				var bEqual;
				if(me.compareMode==0) {
					bEqual = (arr[i] === arr[i+1]);	//二进制比较
                } else {
					bEqual = (arr[i] == arr[i+1]);	//文本比较
                }
				if(bEqual) {
					bRepeat = true;
					break;
				}
			}
		}
		return bRepeat;
	}
};

utils.toJSONString = function(object) {
    var type = typeof object;
    if ('object' == type) {
        if (Array == object.constructor) type = 'array';
        else if (RegExp == object.constructor) type = 'regexp';
        else type = 'object';
    }
    switch (type) {
        case 'undefined':
        case 'unknown':
            return;
            break;
        case 'function':
        case 'boolean':
        case 'regexp':
            return object.toString();
            break;
        case 'number':
            return isFinite(object) ? object.toString() : 'null';
            break;
        case 'string':
            return '"' + object.replace(/(\\|\")/g, "\\$1").replace(/\n|\r|\t/g, function () {
                var a = arguments[0];
                return (a == '\n') ? '\\n' : (a == '\r') ? '\\r' : (a == '\t') ? '\\t' : "";
            }) + '"';
            break;
        case 'object':
            if (object === null) return 'null';
            var results = [];
            for (var property in object) {
                var value = utils.toJSONString(object[property]);
                if (value !== undefined) {
                	results.push(utils.toJSONString(property) + ':' + value);
                }
            }
            return '{' + results.join(',') + '}';
            break;
        case 'array':
            var results = [];
            for (var i = 0; i < object.length; i++) {
                var value = utils.toJSONString(object[i]);
                if (value !== undefined) {
                	results.push(value);
                }
            }
            return '[' + results.join(',') + ']';
            break;
    }
};

utils.utf16to8 = function(str) {
	var out = "";
	var len = str.length;
	for(var i = 0; i < len; i++) {
	    var c = str.charCodeAt(i);
	    if ((c >= 0x0001) && (c <= 0x007F)) {
	        out += str.charAt(i);
	    } else if (c > 0x07FF) {
	        out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
	        out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
	        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
	    } else {
	        out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
	        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
	    }
	}
	return out;
};

utils.utf8to16 = function(str) {
	 var out, i, len, c;
	var char2, char3;
	
	out = "";
	len = str.length;
	i = 0;
	while(i < len) {
	    c = str.charCodeAt(i++);
	    switch(c >> 4) {
	        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
	            // 0xxxxxxx
	            out += str.charAt(i-1);
	            break;
	        case 12: case 13:
	            // 110x xxxx   10xx xxxx
	            char2 = str.charCodeAt(i++);
	            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
	            break;
	        case 14:
	            // 1110 xxxx 10xx xxxx 10xx xxxx
	            char2 = str.charCodeAt(i++);
	            char3 = str.charCodeAt(i++);
	            out += String.fromCharCode(((c & 0x0F) << 12) |
	            ((char2 & 0x3F) << 6) |
	            ((char3 & 0x3F) << 0));
	            break;
	    }
	}
	return out;
};

utils.htmlEncode = function(str) {
	if (str.length == 0) {
		return "";
	}
	
	var s = str.replace(/&/g, "&gt;")
		.replace(/&/g, "&amp;")
		.replace(/</g, "&lt;")
		.replace(/>/g, "&gt;")
		.replace(/ /g, "&nbsp;")
		.replace(/\'/g, "'")
		.replace(/\"/g, "&quot;")
		.replace(/\n/g, "<br>");
	
	return s;
},
    
utils.htmlDecode = function(str) {
	if (str.length == 0) {
		return "";
	}
	
	var s = str.replace(/&gt;/g, "&")
		.replace(/&amp;/g, "&")
		.replace(/&lt;/g, "<")
		.replace(/&gt;/g, ">")
		.replace(/&nbsp;/g, " ")
		.replace(/'/g, "\'")
		.replace(/&quot;/g, "\"")
		.replace(/<br>/g, "\n");
	
	return s;
},

//客户端Base64编码
utils.base64Encode = function(str) {
  str = utils.utf16to8(str);
    var out, i, j, len, r, l, c;
    i = j = 0;
    len = str.length;
    r = len % 3;
    len = len - r;
    l = (len / 3) << 2;
    if (r > 0) {
        l += 4;
    }
    out = new Array(l);

    while (i < len) {
        c = str.charCodeAt(i++) << 16 |
            str.charCodeAt(i++) << 8  |
            str.charCodeAt(i++);
        out[j++] = base64EncodeChars[c >> 18]
            + base64EncodeChars[c >> 12 & 0x3f]
            + base64EncodeChars[c >> 6  & 0x3f]
            + base64EncodeChars[c & 0x3f] ;
    }
    if (r == 1) {
        c = str.charCodeAt(i++);
        out[j++] = base64EncodeChars[c >> 2]
            + base64EncodeChars[(c & 0x03) << 4]
            + "==";
    } else if (r == 2) {
        c = str.charCodeAt(i++) << 8 |
            str.charCodeAt(i++);
        out[j++] = base64EncodeChars[c >> 10]
                + base64EncodeChars[c >> 4 & 0x3f]
                + base64EncodeChars[(c & 0x0f) << 2]
                + "=";
    }
    return out.join('');
};

//客户端Base64解码
utils.fromBase64String = function(str) {
  var c1, c2, c3, c4;
    var i, j, len, r, l, out;

    len = str.length;
    if (len % 4 != 0) {
        return '';
    }
    if (/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+\/\=]/.test(str)) {
        return '';
    }
    if (str.charAt(len - 2) == '=') {
        r = 1;
    }
    else if (str.charAt(len - 1) == '=') {
        r = 2;
    }
    else {
        r = 0;
    }
    l = len;
    if (r > 0) {
        l -= 4;
    }
    l = (l >> 2) * 3 + r;
    out = new Array(l);

    i = j = 0;
    while (i < len) {
        // c1
        c1 = base64DecodeChars[str.charCodeAt(i++)];
        if (c1 == -1) break;

        // c2
        c2 = base64DecodeChars[str.charCodeAt(i++)];
        if (c2 == -1) break;

        out[j++] = String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

        // c3
        c3 = base64DecodeChars[str.charCodeAt(i++)];
        if (c3 == -1) break;

        out[j++] = String.fromCharCode(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));

        // c4
        c4 = base64DecodeChars[str.charCodeAt(i++)];
        if (c4 == -1) break;

        out[j++] = String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return utils.utf8to16(out.join(''));
};

utils.toProxyArray = function(args) {
    var n = args.length;
    var argArray = new Array(n);
    for (var i = 0; i < n - 1; i++) {
        argArray[i] = utils.toJSONString(args[i]);
    }

    if (n > 0) {
        argArray[n - 1] = args[n - 1];
    }

    return argArray;
};

utils.formatSeconds = function(seconds) {
	var s = seconds % 60;
	var mins = ((seconds - s) % 3600) / 60;
	var hours = ((seconds - s - mins*60) % 86400) / 3600;
	
	if (s == 0) {
		s = '00';
	} else if (s < 10) {
		s = '0' + s;
	}
	
	if (hours > 0) {
		return hours + ':' + mins + ':' + s;
	} else if(mins > 0) {
		return mins + ':' + s;
	} 

	return '00:' + s;
};

utils.isEmail = function(s){
	if(typeof s != 'undefined'){
		return /^(?:[\w]+\.?[\w]+)+@(?:[\w]+\.?[\w]+)+\.[a-zA-Z]{2,4}$/.test(s);
	}
	return false;
};

utils.isNumber = function(s){
	if(s == undefined){
		return false;
	}
	
	s = String(s);
	var len = s.length;
	var dot = false;
	var c = s.charCodeAt(0);
	if(c == 43 || c == 45 || (c >= 48 && c <= 57) ){
		for ( var i = 1; i < len; i++) {
			var code = s.charCodeAt(i);
			if(code == 46){
				if(dot === true){
					return false;
				}else{
					dot = true;
				}
			}else if( code < 48 || code > 57){
				return false;
			}
		}
		
		return true;
	}
	
	return false;
};

utils.isInt = function(s){
	if(s == undefined){
		return false;
	}
	s = String(s);
	var len = s.length;
	var c = s.charCodeAt(0);
	if(c == 43 || c == 45 || (c >= 48 && c <= 57) ){
		for ( var i = 1; i < len; i++) {
			var code = s.charCodeAt(i);
			if(code < 48 || code > 57){
				return false;
			}
		}
		
		return true;
	}
	return false;
};